﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

using Blog.TemplateEngine;
using Blog.TemplateEngine.Helpers;

using Blog.TemplateViewEngine;

namespace Blog.TemplateViewEngine.Functions
{
    class RenderPartialFunction : IFunction
    {
        TemplateViewFactory mTemplateViewFactory;

        public RenderPartialFunction(TemplateViewFactory templateViewFactory)
        {
            mTemplateViewFactory = templateViewFactory;
        }

        protected INode Compile(Parser parser, Token token)
        {
            IDictionary<string, IParameter> source = token.Content.ParseNamedVariables(':');

            IParameter template = null;
            Dictionary<string, IParameter> parameters = new Dictionary<string, IParameter>();

            foreach (KeyValuePair<string, IParameter> param in source)
            {
                switch (param.Key)
                {
                    case "template":
                        {
                            template = param.Value;
                        }
                        break;
                    default:
                        {
                            parameters[param.Key] = param.Value;
                        }
                        break;
                }
            }

            if (template == null)
            {
                throw new TemplateException("'render_partial' requires a template parameter: render_partial template:'template' [name1:value1 name2:value2]");
            }

            return new RenderPartialNode(template, parameters, mTemplateViewFactory);
        }

        INode IFunction.Compile(Parser parser, Token token)
        {
            return Compile(parser, token);
        }
    }

    class RenderPartialNode : INode
    {
        IParameter mTemplate;
        IDictionary<string, IParameter> mParameters;
        TemplateViewFactory mTemplateViewFactory;

        public RenderPartialNode(IParameter template, IDictionary<string, IParameter> parameters, TemplateViewFactory templateViewFactory)
        {
            mTemplate = template;
            mParameters = parameters;
            mTemplateViewFactory = templateViewFactory;
        }

        protected string Render(Context context)
        {
            context.Push();

            foreach (KeyValuePair<string, IParameter> parameter in mParameters)
            {
                context[parameter.Key] = parameter.Value.Value(context);
            }

            TemplateView partialView = mTemplateViewFactory.CreatePartial(mTemplate.AsString(context), (ViewContext)context["Mvc.ViewContext"]);

            string result = partialView.RenderView(context);

            context.Pop();

            return result;
        }

        string INode.Render(Context context)
        {
            return Render(context);
        }
    }
}
